定位功能

最后更新时间:2019年6月17日

功能介绍

定位功能,不管是在大众移动应用或者行业GIS应用中,都是非常重要的功能,应用极其广泛。例如,在手机地图导航应用中,通过定位能够知道用户当前所在的位置;在社交通讯类应用中,也可将自己的位置分享给其他人,实现位置的共享;在诸如“悦动圏”、“咕咚”等运动类应用中,通过定位,能够记录用户运动的轨迹;在行业应用中,则常用于数据采集、移动巡检、移动执法等多种方面。

MapGIS Mobile 10.3 for Android SDK提供了室内外一体化的定位模块,室外定位主要依靠GPS卫星获取定位,室内定位采用的技术主要包括:基于WiFi位置指纹数据的WiFi定位技术,以及IMU惯性定位技术。

1
定位功能

室内外一体化定位功能,开发者可根据实际需求使用,在此实现室外定位功能。

功能接口

定位功能对应API程序包为com.zondy.mapgis.android.location,其核心类为定位管理器类LocationManager、定位参数类LocationManagerOption、定位类Location。核心接口如下:

接口 说明
setLocationOption() 设置定位参数
addLocationListener() 添加定位监听者
addDevicePoseListener() 添加设备姿态监听者
addDeviceStatusListener() 添加设备状态监听者
setCustomLocationProvider() 设置自定义位置提供者
startLocation() 开始定位
stopLocation() 结束定位
接口 说明
setInterval() 设置时间间隔
setLocationCoordType() 设置坐标点空间参照系类型,默认为GCJ02经纬度

实现方法

MapGIS Mobile 10.3 for Android SDK提供了室内外一体化的定位模块,室外定位的实现与室内定位的实现方式类似,采用同一套定位接口来实现,实现大体步骤如下所示:

(1)构造定位管理者对象,设置相关信息:构造定位管理对象LocationManager,设置定位监听等信息。

(2)定位参数设置:构造定位参数对象LocationManagerOption,设置位置采集时间间隔、坐标点空间参照系类型信息。然后将定位参数赋予给定位管理对象。

(3)开始定位:调用LocationManager类的startLocation()方法开始定位。

说明:在实现定位功能之前,必须确保应用程序具备进行精确定位、连接网络的权限。需要为工程声明权限的使用,在AndroidManifest.xml清单文件中添加以下权限标签说明:

<!-- 允许应用程序访问精确位置,通过GPS进行定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 允许应用程序访问近似位置,通过网络进行定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 允许应用程序访问网络,可能产生GPRS流量 -->
<uses-permission android:name="android.permission.INTERNET" />

室外定位 Sample详情

1

构造定位管理者对象

LocationManager是定位管理器,是实现定位功能最核心的类,大多定位的相关操作都由此类提供。

//定位管理器
LocationManager locationManager = new LocationManager(getApplicationContext());
//添加定位监听器
locationManager.addLocationListener(mlocationListener);

2

定位参数设置

设置位置信息的采集时间间隔、坐标点空间参照系类型信息。

//定位参数
LocationManagerOption locationManagerOption = new LocationManagerOption();
//设置时间间隔,单位:毫秒
locationManagerOption.setInterval(500);
//设置坐标点空间参照系类型,默认为GCJ02经纬度
locationManagerOption.setLocationCoordType(LocationCoordType.COORD_TYPE_WGS84_LonLat);

//设置定位参数
locationManager.setLocationOption(locationManagerOption);

3

开始定位

准备工作完成后就可调用startLocation接口开始定位。

//开始定位
locationManager.startLocation();

4

定位信息获取

//定位监听器
private LocationManager.LocationListener mlocationListener = new LocationManager.LocationListener() {
    @Override
    public void onLocationChanged(Location location) {
        if (location == null) {
            //定位失败
            return;
        }

        //错误码
        LocationErrorCode locationErrorCode = location.getErrorCode();
        //判断错误码
        if (locationErrorCode == LocationErrorCode.LOCATION_SUCCESS) {
            //定位成功
            //获取定位信息
            getLocationInfo(location);
        } else if (locationErrorCode == LocationErrorCode.ErrorCodeFailureCell) {
            //错误信息:错误的基站信息,请检查是否安装SIM卡
        } else if (locationErrorCode == LocationErrorCode.ErrorCodeFailureConnection) {
            //错误信息:网络连接异常
        } else if (locationErrorCode == LocationErrorCode.ErrorCodeFailureInit) {
            //错误信息:初始化错误
        } else if (locationErrorCode == LocationErrorCode.ErrorCodeFailureNoenoughSatellites) {
            //错误信息:GPS定位失败,可用卫星数不足
        } else if (locationErrorCode == LocationErrorCode.ErrorCodeFailureNoWifiAndAp) {
            //错误信息:网络定位失败,请检查设备是否插入sim卡、开启移动网络或开启了wifi模块
        } else if (locationErrorCode == LocationErrorCode.ErrorCodeUnknown) {
            //错误信息:其他错误
        }
    }
};
//获取定位信息
private void getLocationInfo(Location location) {
    //经度
    double longitude = location.getLongitude();
    //纬度
    double latitude = location.getLatitude();
    //高程
    double altitude = location.getAltitude();
    //方向角
    float bearing = location.getBearing();
    //精度
    float accuracy = location.getAccuracy();
    //速度
    double speed = location.getSpeed();
    //时间
    String time = location.getTime();

    //坐标类型
    LocationCoordType locationCoordType = location.getCoordType();
    //定位类型
    LocationType locationType = location.getLocationType();
    String sLocationType = "";
    if (locationType.equals(LocationType.LocationTypeCELL)) {
        sLocationType = "CELL定位类型";
    } else if (locationType.equals(LocationType.LocationTypeGNSS)) {
        sLocationType = "GNSS定位类型";
    } else if (locationType.equals(LocationType.LocationTypeGNSSExt)) {
        sLocationType = "GNSSEXT定位类型";
    } else if (locationType.equals(LocationType.LocationTypeIMU)) {
        sLocationType = "IMU定位类型";
    } else if (locationType.equals(LocationType.LocationTypeWIFI)) {
        sLocationType = "WIFI定位类型";
    } else if (locationType.equals(LocationType.LocationTypeWIFINet)) {
        sLocationType = "WIFINet定位类型";
    } else if (locationType.equals(LocationType.LocationTypeNone)) {
        sLocationType = "无";
    }
}
//显示定位图标
private void showLocationImg(Location location) {
    //经度
    double longitude = location.getLongitude();
    //纬度
    double latitude = location.getLatitude();
    //定位坐标点
    Dot dot = new Dot(longitude, latitude);

    //绘制定位图标
    if (locationGraphicImage == null) {
        locationGraphicImage = new GraphicImage();
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ico_main_location);
        locationGraphicImage.setImage(bitmap);
        locationGraphicImage.setAnchorPoint(new PointF(0.5f, 0.5f));  //锚点
        mapView.getGraphicsOverlay().addGraphic(locationGraphicImage);
    }
    locationGraphicImage.setPoint(dot);
    mapView.refresh();
}

定位代码实现完成后,调试运行程序。室外定位主要依赖于GPS卫星定位技术,所以在获取定位之前,需要开启手机的GPS定位模块。

实现效果如下图所示:

室外定位.jpg

室内定位 Sample详情

由于MapGIS Mobile提供的室内定位技术主要依赖于WiFi指纹数据定位技术、IMU惯性定位技术,所以决定了室内和室外定位的实现流程不同,室内定位需要进行一系列的数据准备工作,大体分为以下几个步骤,具体操作参考数据组织配置 > 室内定位数据组织

(1)制作、配置室内地图:利用MapGIS桌面软件制作建筑物的室内地图,作为WiFi指纹数据采集的标准、基础。

(2)使用室内定位数据采集工具完成地图数据采集:安装WiFi指纹数据采集工具——“WiFiFingerprintDataAcquisitionTool”APP,利用其完成样本数据采集工作,得到.db格式的数据文件。

(3)使用指纹数据库转换工具完成采集数据库的预处理:利用室内定位指纹数据库转换工具将采集得到的指纹数据库进行预处理,主要是对数据库的存储结构进行优化,并滤除移动的热点以提高定位精度。会将数据格式进行转换,得到最终定位所需要的定位指纹数据库.mrdb格式文件。

(4)使用生成的指纹数据库在SDK中实现定位:生成指纹数据库之后,在MapGIS环境初始化目录下创建radiomaps文件夹,并将指纹数据库存放在此路径下,程序会自动检测。然后在程序中调用定位实现代码。

室内定位的代码实现方法和室外定位的类似,区别在于室内定位情况下根据Location能够获取到楼栋、楼层信息。

//楼层
int floor = location.getFloor();
//判断楼层信息是否可用:如果配置了室内指纹数据,会自动检测
if (floor != Location.INVALID_FLOOR) {
    //楼层信息可用
    //楼栋id
    int buildingID = location.getBuildingID();
    if (floor != Integer.MAX_VALUE) { //室内
        Log.e("室内定位信息", "楼栋号:" + buildingID + "\n楼层号:" + (floor + 1));
    } else { //室外
        Log.e("室内定位信息", "楼栋号:" + buildingID + "\n楼层号:" + floor);
    }
} else {
    //楼层信息不可用
    Log.e("定位信息", "室内定位楼层信息不可用!");
}

说明:配置了室内指纹数据后,程序会自动检测当前位置是否属于室内楼栋数据定位之内,进而获取楼栋和楼层信息。

功能实现代码完成后,可调试运行到真机上,开启手机的WiFi连接、定位模块后,就可获取到当前位置。实现效果如下图所示:

室内定位.jpg